with ada.Text_IO;
use ada.Text_IO;
package sudoku is

   --private types
   type square is private;
   type squarePtr is access square;
   type boardObject is tagged private;
   type row is private;
   type column is private;
   type sub is private;

   --common ranges
   subtype boardSize is Integer range 1..9;

   --arrays
   type possibleArray is array(boardSize) of Boolean;
   type boardArray is array(boardSize, boardSize) of square;
   type rowArray is array(boardSize) of row;
   type columnArray is array(boardSize) of column;
   type subArray is array(boardSize) of sub;

   --main procedures
   procedure printSolution;
   procedure doPuzzle(puzzleFile : file_type);
   procedure getPuzzle(puzzleFile : file_type);

   -- "rule 1"
   procedure updatePuzzle;
   -- "rule 2"
   procedure fillPuzzle;
   -- "rule 3"
   procedure crossHatch;

   --help checkPuzzle
   procedure checkRowsAndColumns(x : in Integer; y : in Integer);
   procedure checkSub(x : in Integer; y : in Integer);

   --help fillPuzzle
   procedure fillRow(rowNum : in Integer; value : in Integer);
   procedure fillColumn(colNum : in Integer; value : in Integer);
   procedure fillSub(subNum : in Integer; value : in Integer);

   --help crossHatch
   procedure crossHatchRow(subNum : in Integer);
   procedure crossHatchColumn(subNum : in Integer);

   --general functions
   procedure checkSquare(x : in Integer; y : in Integer);
   procedure solveSquare(x : in Integer; y : in Integer; value : in Integer);
   procedure solveBoardObject(item : in out boardObject'Class; value : in Integer);
   function isSolved return Boolean;
   function emptySquare(value : in Character) return square;
   procedure reset(item : in out rowArray);
   procedure reset(item : in out columnArray);
   procedure reset(item : in out subArray);
   procedure reset(item : in out possibleArray);

private
   type square is
      record
         value : Character;
         solved : Boolean;
         possible : possibleArray;
         subNum : Integer;
      end record;

   --board object can be a row, column, or subsection
   type boardObject is tagged
      record
         solved : Boolean;
         possible : possibleArray;
      end record;

   type row is new boardObject with null record;
   type column is new boardObject with null record;
   --sub sections are harder to reference, so I keep track of the topleft x,y coordinate for each subsection
   type sub is new boardObject with
      record
         x, y : Integer;
      end record;

end sudoku;
